﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace JustTank
{
    public class Engine
    {
        IRenderer renderer;
        IUserInterface userInterface;
        List<GameObject> allObjects;
        List<MovingObject> movingObjects;
        List<GameObject> staticObjects;
        TankHuman playerTank;
        private int sleepTime;
        private static bool flag = true;

        public Engine(IRenderer renderer, IUserInterface userInterface, int sleepTime)
        {
            this.renderer = renderer;
            this.userInterface = userInterface;
            this.allObjects = new List<GameObject>();
            this.movingObjects = new List<MovingObject>();
            this.staticObjects = new List<GameObject>();
            this.sleepTime = sleepTime;
        }

        private void AddStaticObject(GameObject obj)
        {
            this.staticObjects.Add(obj);
            this.allObjects.Add(obj);
        }

        private void AddMovingObject(MovingObject obj)
        {
            this.movingObjects.Add(obj);
            this.allObjects.Add(obj);
        }

        public virtual void AddObject(GameObject obj)
        {
            if (obj is MovingObject)
            {
                this.AddMovingObject(obj as MovingObject);

                if (obj is TankHuman)
                {
                    AddTank(obj as TankHuman);
                }
            }
            else
            {
                this.AddStaticObject(obj);                    
            }

        }

        private void AddTank(TankHuman obj)
        {
            this.playerTank = obj as TankHuman;
            this.AddMovingObject(obj as MovingObject);
        }

        public virtual void MovePlayerTankLeft()
        {
            this.playerTank.Direction = TankDirection.Left;
            this.playerTank.Update();
            this.playerTank.MoveLeft();
        }

        public virtual void MovePlayerTankRight()
        {
            this.playerTank.Direction = TankDirection.Right;
            this.playerTank.Update();
            this.playerTank.MoveRight();
        }

        public virtual void MovePlayerTankUp()
        {
            this.playerTank.Direction = TankDirection.Up;
            this.playerTank.Update();
            this.playerTank.MoveUp();
        }

        public virtual void MovePlayerTankDown()
        {
            this.playerTank.Direction = TankDirection.Down;
            this.playerTank.Update();
            this.playerTank.MoveDown();
        }

        public virtual void ShootPlayrTank()
        {
            this.playerTank.ShootBullet();
        }

        public virtual void Run()
        {          
            
            while (true)
            {

                this.renderer.RenderAll();

                System.Threading.Thread.Sleep(this.sleepTime);

                this.userInterface.ProcessInput();

                this.renderer.ClearQueue();

                foreach (var obj in this.allObjects)
                {
                    if (!(obj is Tank && flag))
                    {
                        obj.Update();
                    }
                    
                    this.renderer.EnqueueForRendering(obj);
                }

                flag ^= true;

                CollisionDispatcher.HandleCollisions(this.movingObjects, this.staticObjects);

                List<GameObject> producedObjects = new List<GameObject>();

                foreach (var obj in this.allObjects)
                {
                    producedObjects.AddRange(obj.ProduceObjects());
                }

                this.allObjects.RemoveAll(obj => obj.IsDestroyed);
                this.movingObjects.RemoveAll(obj => obj.IsDestroyed);
                this.staticObjects.RemoveAll(obj => obj.IsDestroyed);

                foreach (var obj in producedObjects)
                {
                    this.AddObject(obj);
                }

                if (this.playerTank.IsDestroyed == true)
                {
                    return;
                }

            }
        }

        
    }
}
